//二进制编码/解码模块

/* 规定:
(1)服务号 命令号 不能为0
(2)服务号与命令号大小不能超过2个字节的整数;
(3) buf协议里面2个字节来存放服务号(0开始的2个字节)，命令号(1开始的2个字节);
(4) 加密,解密, 
(5) 服务号命令号二进制中都用小尾存储
(6) 所有的文本，都使用utf8
*/
// var log = require("../utils/log.js");

var log = {
	info: console.log,
	warn: console.log,
	error: console.log,
}

var proto_man = {
	PROTO_JSON: 1,   //json 协议
	PROTO_BUF: 2,    //二进制协议
	encode_cmd: encode_cmd,
	decode_cmd: decode_cmd,
	reg_decoder: reg_buf_decoder,
	reg_encoder: reg_buf_encoder
};

// 加密
function encrypt_cmd(str_of_buf) {
    //加密，暂时不做
	return str_of_buf;
}

// 解密
function decrypt_cmd(str_of_buf) {
     //解密，暂时不做
	return str_of_buf;
}

/**
 * 编码json
 * @param {*} stype 服务号
 * @param {*} ctype 命令号
 * @param {*} body  数据
 * @returns 
 */
function _json_encode(stype, ctype, body) {
	var cmd = {};
	cmd[0] = stype;
	cmd[1] = ctype;
	cmd[2] = body;

	var str = JSON.stringify(cmd);
	return str;
}

/**
 * 解码json
 * @param {*} cmd_json 
 * @returns 
 */
function json_decode(cmd_json) {

	var cmd = null;
	try {
		cmd = JSON.parse(cmd_json);
		if (!cmd || typeof(cmd[0])=="undefined" || typeof(cmd[1]) =="undefined" || typeof(cmd[2])=="undefined") {
			return null;
		}
	} catch (error) {
		console.log('=========json_decode err==============',error);
	}

	return cmd;
} 

// key, value, stype + ctype -->key: value
/**
 * 将 2个整数 转成一个整数， stype 是不能超过2个字节的，2个字节最大是65535
 * @param {*} stype 
 * @param {*} ctype 
 * @returns 
 */
function get_key(stype, ctype) {
	return (stype * 65536 + ctype);
}

/**
 * 编码二进制
 * @param {*} proto_type  协议类型 json, buf协议;
 * @param {*} stype 服务类型
 * @param {*} ctype 命令号
 * @param {*} body 发送的数据本地，js对象/js文本，...
 * @returns 返回是一段编码后的数据;
 */
function encode_cmd(proto_type, stype, ctype, body) {
	var buf = null;
	if (proto_type == proto_man.PROTO_JSON) {
		buf = _json_encode(stype, ctype, body);
	}
	else { // buf协议
		var key = get_key(stype, ctype);
		if (!encoders[key]) {
			return null;
		}
		// end 
		buf = encoders[key](body);
	}

	if (buf) {
        // 加密
		buf = encrypt_cmd(buf);	
	}
	
	return buf;
}


/**
 * 解码 二进制
 * @param {*} proto_type 协议类型cls
 * @param {*} str_or_buf 接手到的数据命令
 * @returns  返回: {0: stype, 1, ctype, 2: body}
 */
function decode_cmd(proto_type, str_or_buf) {
    // 解密
	str_of_buf = decrypt_cmd(str_or_buf); 

	if (proto_type == proto_man.PROTO_JSON) {
		return json_decode(str_or_buf);
	}

	if(str_or_buf.length < 4){
		return null;
	}

	var cmd = null;
	var stype = str_or_buf.readUInt16LE(0);
	var ctype = str_or_buf.readUInt16LE(2);
	var key = get_key(stype, ctype);

	if (!decoders[key]) {
		return null;
	}

	cmd = decoders[key](str_or_buf);
	return cmd;
}

// buf协议的编码/解码管理  stype, ctype --> encoder/decoder
var decoders = {}; // 保存当前我们buf协议所有的解码函数, stype,ctype --> decoder;
var encoders = {}; // 保存当前我们buf协议所有的编码函数, stype, ctype --> encoder


// encode_func(body)
/**
 * 注册一个编码器
 * @param {} stype 
 * @param {*} ctype 
 * @param {*} encode_func 
 *  return 二进制bufffer对象
 */
function reg_buf_encoder(stype, ctype, encode_func) {
	var key = get_key(stype, ctype);
	if (encoders[key]) { // 已经注册过了，是否搞错了
		log.warn("stype: " + stype + " ctype: " + ctype + "is reged!!!");
	}

	encoders[key] = encode_func;
}

// decode_func(cmd_buf)
/**
 * 注册一个解码器
 * @param {*} stype 服务号
 * @param {*} ctype 命令号
 * @param {*} decode_func 
 *  return cmd { 0: 服务号, 1: 命令号, 2: body};
 */
function reg_buf_decoder(stype, ctype, decode_func) {
	var key = get_key(stype, ctype);
	if (decoders[key]) { // 已经注册过了，是否搞错了
		log.warn("stype: " + stype + " ctype: " + ctype + "is reged!!!");
	}

	decoders[key] = decode_func;
}


module.exports = proto_man;
